<template>
  <Dialog
    :title="`权限配置--${permissionData.entityDisplayName}`"
    @handle-confirm="handleConfirm"
    @open="handleDialogOpen"
  >
    <div class="permissionsFormInner" v-loading="formLoading">
      <el-tabs tab-position="left">
        <el-tab-pane
          v-for="(item, index) in permissionData.groups"
          :key="item.name"
          :label="item.displayName"
        >
          <el-tree
            :ref="(el: any) => (permissionTreeRefs[index] = el)"
            check-strictly
            :data="item.data"
            :props="treeDefaultProps"
            show-checkbox
            default-expand-all
            node-key="name"
            class="permission-tree"
          />
        </el-tab-pane>
      </el-tabs>
    </div>
  </Dialog>
</template>

<script setup lang="ts">
import Dialog from '@/components/Dialog/index.vue'
import { getPermissions, updatePermissions } from '@/http/permissions'
import { getRole } from '@/http/role'
import {
  IGetPermission,
  IGetPermissionRes,
  IPermission,
} from '@/http/types/permissions'
import { IRole } from '@/http/types/role'
import { IUser } from '@/http/types/user'
import { getUser } from '@/http/user'
import { ElNotification } from 'element-plus'
// import { IElTree } from '@/types/element-plus'
import { nextTick, onBeforeUpdate, reactive, ref } from 'vue'

const props = defineProps({
  providerName: {
    type: String,
    default: 'R',
  },
  editId: {
    type: String,
    default: '',
  },
})
interface EmitsType {
  (e: 'success'): void
}
const emit = defineEmits<EmitsType>()
// 树组件 ref 列表
const permissionTreeRefs = ref<any>([])
onBeforeUpdate(() => {
  permissionTreeRefs.value = []
})
// onUpdated(() => {
//   console.log(permissionTreeRefs.value)
// })
const treeDefaultProps = {
  children: 'children',
  label: 'label',
}
const permissionData = reactive<IGetPermissionRes>({
  entityDisplayName: '',
  groups: [],
})
const handleConfirm = async () => {
  const tempData: {
    isGranted: boolean
    name: string
  }[] = []
  for (const i in permissionData.groups) {
    const keys = permissionTreeRefs.value[i].getCheckedKeys()
    const group = permissionData.groups[i]
    for (const j in group.permissions) {
      if (
        group.permissions[j].isGranted &&
        !keys.some((v: string) => v === group.permissions[j].name)
      ) {
        tempData.push({
          isGranted: false,
          name: group.permissions[j].name,
        })
      } else if (
        !group.permissions[j].isGranted &&
        keys.some((v: string) => v === group.permissions[j].name)
      ) {
        tempData.push({ isGranted: true, name: group.permissions[j].name })
      }
    }
  }
  await updatePermissions(
    { providerKey: providerKey.value, providerName: props.providerName },
    { permissions: tempData },
  )
  ElNotification({
    title: '保存成功',
    message: '用户权限设置成功',
    type: 'success',
    duration: 2000,
  })
  emit('success')
}
const providerKey = ref('')
const handleGetPermissions = async (row: IUser | IRole) => {
  props.providerName === 'R'
    ? (providerKey.value = row.name)
    : (providerKey.value = row.id || '')
  const res = await getPermissions({
    providerName: props.providerName,
    providerKey: providerKey.value,
  })
  permissionData.entityDisplayName = res.entityDisplayName
  permissionData.groups = res.groups
  permissionData.groups.forEach((item) => {
    item.data = transformPermissionTree(item.permissions)
  })
  const defaultKeys: Array<string[]> = []
  for (const i in permissionData.groups) {
    const group = permissionData.groups[i]
    const keys: string[] = group.permissions
      .filter((e) => e.isGranted)
      .map((e) => e.name)
    defaultKeys.push(keys)
  }
  await nextTick()
  defaultKeys.forEach((keys, i) => {
    permissionTreeRefs.value[i].setCheckedKeys(keys)
  })
}
interface ITreeItem {
  name: string
  label: string
  disabled: boolean
  children: ITreeItem[]
}
const transformPermissionTree = (
  permissions: IPermission[],
  name: string | null = null,
) => {
  const arr: ITreeItem[] = []
  if (!permissions || !permissions.some((v) => v.parentName === name)) {
    return arr
  }

  const parents = permissions.filter((v) => v.parentName === name)
  for (const i in parents) {
    let label = ''
    if (props.providerName === 'R') {
      label = parents[i].displayName || ''
    } else if (props.providerName === 'U') {
      label =
        parents[i].displayName +
        ' ' +
        (parents[i].grantedProviders || []).map((provider) => {
          return `${provider.providerName}: ${provider.providerKey}`
        })
    }
    arr.push({
      name: parents[i].name,
      label,
      disabled: isGrantedByOtherProviderName(parents[i].grantedProviders || []),
      children: transformPermissionTree(permissions, parents[i].name),
    })
  }
  return arr
}
const isGrantedByOtherProviderName = (grantedProviders: IGetPermission[]) => {
  if (grantedProviders.length) {
    return (
      grantedProviders.findIndex((p) => p.providerName !== props.providerName) >
      -1
    )
  }
  return false
}
const formLoading = ref(false)
const handleDialogOpen = async () => {
  formLoading.value = true
  let data: IUser | IRole | null = null
  if (props.providerName === 'R') {
    data = await getRole(props.editId)
  } else if (props.providerName === 'U') {
    data = await getUser(props.editId)
  }
  if (data) {
    await handleGetPermissions(data).finally(() => {
      formLoading.value = false
    })
  }
}
// const loadRole = async () => {
//   const roleInfo = await getRole(props.editId)
// }
// const loadUser = async () => {
//   const userInfo = await getUser(props.editId)
// }
</script>

<style scoped lang="scss"></style>
